package com.hq.utils;

import jakarta.annotation.PostConstruct;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.util.Timeout;
import org.springframework.stereotype.Component;

import java.io.Closeable;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;


/**
 * 初始化 HTTP 客户端：init() 方法初始化 CloseableHttpClient，配置连接池、请求超时和套接字超时。
 * 连接池配置：通过 PoolingHttpClientConnectionManagerBuilder 设置最大连接数（1000）和每路由的最大连接数（50），用于高并发场景。
 * 请求配置：包括连接超时、请求超时和响应超时，确保在合理的时间内处理请求。
 * HTTP 请求处理：
 * GET/HEAD 请求：getOrHead() 方法可发送 GET 或 HEAD 请求，并接受自定义请求头。
 * POST 请求：post() 方法可发送 POST 请求，支持自定义请求头和实体。
 * 资源管理：closeQuietly() 方法用于关闭资源，避免抛出异常
 **/

@Component
public class HttpClient {

    private CloseableHttpClient httpClient;

    /**
     * 初始化线程池
     */
    @PostConstruct
    public void init() {
        SocketConfig socketConfig = SocketConfig.custom()
                .setSoTimeout(Timeout.ofMilliseconds(1000))
                .build();

        PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder
                .create()
                .setDefaultSocketConfig(socketConfig)
                .setMaxConnTotal(1000)
                .setMaxConnPerRoute(200)
                .build();

        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(Timeout.ofMilliseconds(8000))
                .setResponseTimeout(Timeout.ofMilliseconds(8000))
                .setConnectTimeout(Timeout.ofMilliseconds(8000))
                .build();

        httpClient = HttpClients
                .custom()
                .disableContentCompression()
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(requestConfig)
                .build();
    }


    public CloseableHttpResponse getOrHead(String url, String method, Map<String, String> headers) throws IOException {
        HttpUriRequestBase request = new HttpUriRequestBase(method, URI.create(url));
        BasicHeader[] head = mapToHeaders(headers);
        request.setHeaders(head);
        return httpClient.execute(request);
    }

    /**
     * get 请求返回请求体字符
     *
     * @param url 请求路径
     * @return 成功返回请求体 失败返回 空
     */
    public final String getString(String url) {
        try {

            // 1、构建入参、添加 headers


            // 2、发起http请求
            CloseableHttpResponse httpResponse = this.getOrHead(url, "GET", this.NewResponseHeader());

            // 3、返回结果，异常处理
            if (httpResponse.getCode() == 200) {
                //获取请求数据
                return EntityUtils.toString(httpResponse.getEntity());


            }
        } catch (Exception e) {
            return null;
        }

        return null;
    }

    /**
     * 模拟 qq 浏览器请求头
     *
     * @return 返回请求头
     */
    public final Map<String, String> NewResponseHeader() {
        Map<String, String> headers = new HashMap<>();
        headers.put("Sec-Ch-Ua", "Not)A;Brand;v=24, Chromium;v=116");
        headers.put("Sec-Ch-Ua-Mobile", "?0");
        headers.put("Sec-Ch-Ua-Platform", "Windows");
        headers.put("Sec-Fetch-Dest", "document");
        headers.put("Sec-Fetch-Mode", "navigate");
        headers.put("Sec-Fetch-Site", "same-origin");
        headers.put("Sec-Fetch-User", "?1");
        headers.put("Upgrade-Insecure-Requests", "1");
        String useragent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.97 Safari/537.36 Core/1.116.438.400 QQBrowser/13.0.6071.400";
        headers.put("user-agent", useragent);
        return headers;
    }

    public CloseableHttpResponse post(String url, Map<String, String> headers, HttpEntity httpEntity) throws IOException {
        HttpPost request = new HttpPost(url);
        BasicHeader[] head = mapToHeaders(headers);
        request.setHeaders(head);
        request.setEntity(httpEntity);
        return httpClient.execute(request);
    }

    public static BasicHeader[] mapToHeaders(Map<String, String> map) {
        BasicHeader[] headers = new BasicHeader[map.size()];
        int i = 0;
        for (Map.Entry<String, String> entry : map.entrySet()) {
            headers[i++] = new BasicHeader(entry.getKey(), entry.getValue());
        }
        return headers;
    }

    public static void closeQuietly(Closeable is) {
        if (is != null) {
            try {
                is.close();
            } catch (Exception ex) {
                System.out.println("Resources encounter an exception when closing，ex：{}\n" + ex.getMessage());
            }
        }
    }

}